<template>
    <div class="input-inline" :class="{ focus: focus }" contentEditable="true" spellcheck="false" ref="content" v-html="html" @input="onInput($event)" @blur="onBlur($event)" @focus="onFocus($event)" @compositionstart="typing = true" @compositionend="typing = false;onInput($event);" @paste="onPaste($event)" @keydown.enter="onEnter($event)"></div>
</template>

<script>
export default {
    name: "InputInline",
    props: {
        value: { type: String, required: true },
    },
    data () {
        return {
            style: null,
            focus: false,
            html: "",
            text: "", // 当前html对应的text缓存
            typing: false, // 是否是输入法正在输入
            remind: null, // @用户时输入
            cache: "",
            fullContent: "",
        };
    },
    watch: {
        value (newstr, oldstr) {
            // 如果解析内容与当前html不一至，则生成content
            if (this.text == newstr) {
                return;
            }
            this.text = newstr;
            this.html = this.getHtml(newstr);
            this.$refs.content.innerHTML = this.html;
        },
    },

    methods: {
        // 显示删除提示提示
        onInput (event) {
            // 当换行时，去掉多余标签
            // 当粘贴时，去掉多余标签

            const html = this.$refs.content.innerHTML;
            this.text = this.getText(html);


            // 纯文字,选中文字后，ctrl + b 变粗体问题
            if (this.text != html) {
                this.html = this.text;
                this.$refs.content.innerHTML = this.text;
                this.setFocus(event);
            }


            // let _words = this.text;
            // if (!this.typing) {
            //     let num = this.text.length;

            //     if (num >= 3000) {
            //         num = 3000;
            //         // event.target.innerText = _words.substring(0, 3000);
            //         // this.html = _words.substring(0, 3000)
            //         this.text = _words.substring(0, 3000);
            //         this.html = this.getHtml(this.text);
            //         this.$refs.content.innerHTML = this.html;
            //         this.fullContent = _words.substring(0, 3000);
            //         this.setFocus(event);
            //     } else {
            //         this.fullContent = "";
            //     }
            // } else if (this.fullContent) {
            //     // 目标对象：超过3000字时候的中文输入法
            //     // 原由：虽然不会输入成功，但是输入过程中字母依然会显现在输入框内
            //     // 弊端：谷歌浏览器输入法的界面偶尔会闪现
            //     // event.target.innerText = this.fullContent;
            //     // this.text = event.target.innerText;
            //     this.html = this.getHtml(this.fullContent);
            //     this.$refs.content.innerHTML = this.html;
            //     this.typing = false;
            //     this.setFocus(event);
            // }

            this.$emit("input", this.text);
        },

        // 粘贴
        onPaste: function (e) {
            // 监听复制paste事件，目的是为了让-webkit-user-modify属性兼容IE8，毕竟该属性在IE兼容性不好
            e.preventDefault();
            var text = null;
            if (window.clipboardData && clipboardData.setData) {
                // IE
                text = window.clipboardData.getData("text");
            } else {
                text =
                    (e.originalEvent || e).clipboardData.getData(
                        "text/plain"
                    ) || "";
            }

            // 这里的目的是为了将鼠标的光标移动到复制之后文本的末尾的末尾
            if (document.body.createTextRange) {
                if (document.selection) {
                    textRange = document.selection.createRange();
                } else if (window.getSelection) {
                    sel = window.getSelection();
                    var range = sel.getRangeAt(0);
                    // 创建临时元素，使得TextRange可以移动到正确的位置
                    var tempEl = document.createElement("span");
                    tempEl.innerHTML = "&#FEFF;";
                    range.deleteContents();
                    range.insertNode(tempEl);
                    textRange = document.body.createTextRange();
                    textRange.moveToElementText(tempEl);
                    tempEl.parentNode.removeChild(tempEl);
                }
                textRange.text = text;
                textRange.collapse(false);
                textRange.select();
            } else {
                // Chrome之类浏览器
                document.execCommand("insertText", false, text);
            }
        },

        // 失去焦点
        onBlur (event) {
            setTimeout(() => {
                this.style = null;
            }, 200);
            this.$emit("blur", event);
            this.focus = false;
            this.cache != this.text && this.$emit("change", this.text);
        },

        // 失去焦点
        onFocus (event) {
            this.cache = this.text;
            this.focus = true;
            this.$emit("focus", event);
        },

        // 回车
        onEnter (event) {
            event && event.preventDefault && event.preventDefault();
            event && event.stopPropagation && event.stopPropagation();
            event.target.blur();
        },

        // 定位div(contenteditable = "true")；超过字数光标定位到末端
        setFocus (e) {
            let el = this.$refs.content;
            el.focus();
            let range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(false);
            let sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
            this.cache = this.text;
        },

        // 获取光标处样式
        getStyle () {
            if (this.typing) {
                return;
            }

            var text = this.$refs.content.innerText;
            var posa = this.getCursortPosition(this.$refs.content); // 光标所在文本的索引

            // 如果有@，则弹出对话框
            // 获取光标位置
            if (/@\S*?$/.test(text.substring(0, posa))) {
                var rect = this.$el.getBoundingClientRect();
                var pixel = this.getCursortPixel();

                var index = text.lastIndexOf("@");
                var length = text.substring(index).search(/(\s|$)/);
                var name = text.substr(index, length);

                var selection = window.getSelection
                    ? window.getSelection()
                    : null;
                var range = selection
                    ? selection.getRangeAt(0)
                    : document.createRange();

                this.remind = {
                    index: index,
                    length: length,
                    name: name,
                    offset: posa - index,
                    range: range,
                    startOffset: range.startOffset || 0,
                    endOffset: range.endOffset || 0,
                    startContainer: range.startContainer || 0,
                    endContainer: range.endContainer || 0,
                    parentNode: range.endContainer.parentNode,
                };

                // this.style = {
                //     left: pixel.left - rect.left + "px",
                //     top: pixel.top - rect.top + "px",
                // };

            } else {
                this.style = null;
                this.remind = null;
            }
        },


        // 获取光标像素位置
        getCursortPixel () {
            var clonedRange, offset, rect, shadowCaret;
            var selection = window.getSelection ? window.getSelection() : null;
            var range =
                selection && selection.rangeCount > 0
                    ? selection.getRangeAt(0)
                    : null;

            if (window.getSelection && range) {
                if (
                    range.endOffset - 1 > 0 &&
                    range.endContainer !== this.$refs.content
                ) {
                    clonedRange = range.cloneRange();
                    clonedRange.setStart(
                        range.endContainer,
                        range.endOffset - 1
                    );
                    clonedRange.setEnd(range.endContainer, range.endOffset);
                    rect = clonedRange.getBoundingClientRect();
                    offset = {
                        height: rect.height,
                        left: rect.left + rect.width,
                        top: rect.top,
                    };
                    clonedRange.detach();
                }
                if (
                    !offset ||
                    (offset != null ? offset.height : void 0) === 0
                ) {
                    clonedRange = range.cloneRange();
                    shadowCaret = document.createTextNode("|");
                    clonedRange.insertNode(shadowCaret);
                    clonedRange.selectNode(shadowCaret);
                    rect = clonedRange.getBoundingClientRect();
                    offset = {
                        height: rect.height,
                        left: rect.left,
                        top: rect.top,
                    };
                    shadowCaret.remove();
                    clonedRange.detach();
                }
            } else if (document.selection) {
                // ie
                var range = document.selection.createRange().duplicate();
                range.moveStart("character", -1);
                var rect = range.getBoundingClientRect();
                offset = {
                    height: rect.bottom - rect.top,
                    left: rect.left,
                    top: rect.top,
                };
            }
            return offset;
        },

        // 获取光标索引位置
        getCursortPosition (element) {
            var caretOffset = 0;
            var doc = element.ownerDocument || element.document;
            var win = doc.defaultView || doc.parentWindow;
            var sel;
            if (typeof win.getSelection != "undefined") {
                //谷歌、火狐
                sel = win.getSelection();
                if (sel.rangeCount > 0) {
                    //选中的区域
                    var range = win.getSelection().getRangeAt(0);
                    var preCaretRange = range.cloneRange(); //克隆一个选中区域
                    preCaretRange.selectNodeContents(element); //设置选中区域的节点内容为当前节点
                    preCaretRange.setEnd(range.endContainer, range.endOffset); //重置选中区域的结束位置
                    caretOffset = preCaretRange.toString().length;
                }
            } else if ((sel = doc.selection) && sel.type != "Control") {
                //IE
                var textRange = sel.createRange();
                var preCaretTextRange = doc.body.createTextRange();
                preCaretTextRange.moveToElementText(element);
                preCaretTextRange.setEndPoint("EndToEnd", textRange);
                caretOffset = preCaretTextRange.text.length;
            }
            return caretOffset;
        },

        // 插入内容
        insertHtmlAtCaret (html) {
            var sel, range, frag;
            if (window.getSelection) {
                sel = window.getSelection();
                if (sel.getRangeAt && sel.rangeCount) {
                    range = sel.getRangeAt(0);
                    range.deleteContents();
                    var el = document.createElement("div");
                    el.innerHTML = html;
                    frag = document.createDocumentFragment();
                    var node;
                    var lastNode;
                    while ((node = el.firstChild)) {
                        lastNode = frag.appendChild(node);
                    }
                    range.insertNode(frag);
                    if (lastNode) {
                        range = range.cloneRange();
                        range.setStartAfter(lastNode);
                        range.collapse(true);
                        sel.removeAllRanges();
                        sel.addRange(range);
                    }
                }
            }
        },

        // 从text 获取到html结构
        getHtml (text) {
            // demo:
            // '<span uid="1324148" type="1">Abner</span>';
            text = text.replace(/<\$@<\$\$([\w\W]*?)@\$>/gi, function (user) {
                var match =
                    user.match(
                        /<\$@<\$\$([\w\d]*?)-([\w\d]*?)\$\$>([\w\W]*?)@\$>/
                    ) || [];
                var uid = match[1] || "";
                var type = match[2] || "";
                var name = match[3] || "";
                return (
                    '<span uid="' +
                    uid +
                    '" type="' +
                    type +
                    '">' +
                    name +
                    "</span>"
                );
            });
            // 暂不用解析
            return text;
        },

        // 从html内容，解析到text字符串数据
        getText (html) {
            // demo:
            // <$@<$$1324148-1$$>Abner@$>
            // html = html.replace(
            //     /<span [\w\W]*?>[\w\W]*?<\/span>/gi,
            //     function (span) {
            //         var uid = (span.match(/uid=['"]([\w\d_-]*?)['"]/) || [])[1];
            //         var type = (span.match(/type=['"]([\w\d_-]*?)['"]/) ||
            //             [])[1];
            //         var name = (span.match(/>@([\w\W]*?)<\//) || [])[1];
            //         return "<$@<$$" + uid + "-" + type + "$$>" + name + "@$>";
            //     }
            // );

            // html = html.replace(/&nbsp;/gi, " ");
            // 去掉所有标签

            if (html && html.replace) {
                return html.replace(/<[^>]+>/g, "")
            } else {
                return '';
            }

            // return html;
        },
    },
    created () {
        this.text = this.getText(this.value);
        this.html = this.getHtml(this.text);

        // 干掉IE http之类地址自动加链接
        try {
            document.execCommand("AutoUrlDetect", false, false);
        } catch (e) { }
    },
};
</script>
<style lang="scss" scoped>
.input-number {
    position: relative;
    display: flex;
    flex-direction: column;
    span {
        height: 14px;
        font-size: 12px;

        color: #acacac;
        line-height: 14px;
        text-align: left;
        margin-bottom: 4px;
    }

    input {
        width: 100%;
        height: 32px;
        background: #ffffff;
        border-radius: 4px;
        border: 1px solid #d9d9d9;
        box-sizing: border-box;
        padding: 6px 50px 6px 12px;
        font-size: 14px;

        color: #000000;

        &[disabled] {
            background: #eee;
        }
    }

    em {
        position: absolute;
        right: 0;
        bottom: 0;
        height: 32px;
        line-height: 32px;
        right: 40px;
        font-size: 14px;

        color: #aaaaaa;
    }

    b {
        position: absolute;
        bottom: 16px;
        right: 12px;
        width: 16px;
        height: 14px;
        line-height: 14px;
        text-align: center;
        font-size: 12px;
        font-weight: normal;
        cursor: pointer;
        color: #000;

        &:last-child {
            bottom: 2px;
        }
    }
}
</style>
